/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Portions created by the Initial Developer are
 * Copyright (C) 2012 the Initial Developer.
 * All Rights Reserved.
 *
 * The Original Code is "http://semi-frame.googlecode.com/svn/trenk/".
 *
 * The Initial Developer of the Original Code is the author below.
 */
/**
 * @file SocketUtil.h
 * @brief Utility of socket.
 * @author mornongcloud
 * @date 2011/11/21
 */

#ifndef SEMIUTILSOCKETUTIL_H_
#define SEMIUTILSOCKETUTIL_H_

#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "UtilBase.h"
#include <arpa/inet.h> // inet_addr
namespace semi {
namespace util {

// can not receive header over 256 bytes
#define BUFFER_SIZE 256

/**
 * @brief TCP/IP class.
 *
 * Utility of TCP/IP socket.
 *
 * @author morningcloud
 * @date 2010/03/11
 */
class SocketUtil {
public:
	SocketUtil();
	// @brief Constructor for server side.
	SocketUtil(unsigned short port);
	// @brief Constructor for client side.
	SocketUtil(std::string name, unsigned short port);

	void init(unsigned short port, std::string name = std::string(""));

	///@brief destructor.
	virtual ~SocketUtil();

	/**
	 * @brief connect by TCP to server (client side)
	 *
	 * @return connection success.
	 */
	bool tcpConnect(int timeout);

	/**
	 * @brief connection close.
	 */
	void end();

	// @brief send TCP packet.
	bool tcpSend(std::string message, int timeout);
	bool tcpSend(void* message, int size, int timeout);

	// @brief send UDP packet.
	bool udpSend(std::string message);
	bool udpSend(void* message, int size);

	bool tcpListen(int num);
	int tcpAccept();
	int tcpReceive();
	int tcpReceive(int hd_size, int len_size, int len_start = 0);

	bool udpBind();
	int udpReceive();

	void setServerPort(unsigned short port);
	void setDistination(std::string name, unsigned short port);

	// received message
	void* header;
	void* message;

private:

	unsigned short myPort;
	sockaddr_in myAddress;

	std::string distName;
	unsigned short distPort;
	sockaddr_in distAddress;

	int socketNo;

	short size;

	void setupDistination(std::string name, unsigned short port);

	static void signal_alarm_handler(int param);

};

}
}

#endif /* SEMIUTILSOCKETUTIL_H_ */
